package Reeks5.VanRansbeeck.Kevin.Model;

import Reeks5.VanRansbeeck.Kevin.Model.States.Game.SpelStateContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;

/*
 * Model voor "een" kaartspel
 * voorzien: 1 deck en een array van "Spelers" (ook abstract)
 * 
 * hier worden de regels per spel verwerkt
 */
abstract public class Spel extends Observable {
    protected Deck deck;
    protected List<Speler> spelers;
    protected List<Kaart> tafel;
    protected int pot;
    protected SpelStateContext spelContext;
    protected int smallblind;
    protected int maxbet;
    protected int highestbet;

    
    
    public Spel() {
        this(false);
    }
    public Spel(boolean shuffle) {
        this.setDeck(new Deck(shuffle));
        this.spelers = new ArrayList<Speler>();
        this.setTafel();
        this.setSpelContext(new SpelStateContext(this));
        this.setSmallblind(3);
        this.setMaxbet(0);
        this.setTafel();
        this.setHighestbet(0);
    }

    public SpelStateContext getSpelContext() {
        return spelContext;
    }

    private void setSpelContext(SpelStateContext spelContext) {
        this.spelContext = spelContext;
    }
    
    public Deck getDeck() {
        return deck;
    }

    private void setDeck(Deck deck) {
        this.deck = deck;
    }
    
    public List<Speler> getSpelers() {
        return this.spelers;
    }
    
    public int getPot() {
        return pot;
    }

    public void setPot(int pot) {
        this.pot = pot;
    }

    public List<Kaart> getTafel() {
        return tafel;
    }

    abstract void setTafel(); // per spel arraylist declareren van max aantal tafelkaarten
    
    abstract public void addSpeler(Speler s);
    // per spel implementeren 
    // -> PokerSpel kan enkel PokerSpeler toevoegen/verwijderen bvb
    
    public void removeSpeler(Speler s) {
        this.spelers.remove(s);
    }
    
    public void resetDeck() {
        deck.reset(true);
    }
    //abstract public Kaart drawKaart();
    //abstract public Speler decideWinner();
    
    public boolean drawKaart() {
        try {
            Kaart k = deck.neemRandomKaart();
            System.out.println(k + " genomen");
            this.tafel.add(k);
            return true;
        } catch (ArrayIndexOutOfBoundsException aob) {
            System.out.println("One card too many drawn!");
            return false;
        } catch (Exception e) {
            System.out.println(e);
            return false;
        }
    }
    
    public boolean drawAlleSpelersKaart() {
        boolean ok = true;
        
        if(this.getSpelers().size() > 0) {
            for(Speler s : this.getSpelers()) {
                try {
                    if(s.drawKaart() instanceof Kaart)
                        ok = false;
                } catch (ArrayIndexOutOfBoundsException aob) {
                    System.out.println("One card too many drawn!");
                    aob.printStackTrace();
                    System.out.println("______SPELER_____\n" + s);
                    System.out.println("_______DECK______\n" + getDeck());
                    ok = false;
                } catch (Exception e) {
                    System.out.println(e);
                    ok = false;
                }
            }
        }
        
        return ok;
    }
    
    @Override
    public String toString() {     
        String ret = "Kaarten op tafel: \n";
        for(Kaart k : this.getTafel()) {
            if(k.getType() != null) {
                ret += k + "\n";
            } else {
                ret += "***";
            }
        }
        
        ret += "\n" + this.getSpelers().size() + " speler(s):\n";
        if(this.getSpelers().size() > 0) {
            for(Speler s : this.getSpelers()) {
                ret += s + "\n";
            }
        }
        return ret;
    }
    
    

    public int getMaxbet() {
        return maxbet;
    }

    private void setMaxbet(int maxbet) {
        this.maxbet = maxbet;
    }

    public int getSmallblind() {
        return smallblind;
    }

    private void setSmallblind(int smallblind) {
        this.smallblind = smallblind;
    }
    
    public int getHighestbet() {
        return highestbet;
    }

    public void setHighestbet(int highestbet) {
        this.highestbet = highestbet;
    }
    
    public abstract void blinds();

    public abstract void drawFlop();

    public abstract void drawTurn();

    public abstract void drawRiver();
}
